package controllers

import (
	"com.opennews.openplatform/web_api/services"
	"github.com/gin-gonic/gin"
	"net/http"
)

// Sets routes for authentication resource.
func SetAuthenticationRoutes(routerGroup *gin.RouterGroup) {
	controller := NewAuthenticationController()

	routerGroup.POST("/login", controller.Login)
	routerGroup.POST("/refresh-token", controller.RefreshToken)
}

type AuthenticationController interface {
	Login(ctx *gin.Context)
	RefreshToken(ctx *gin.Context)
}

// Returns the instance of private member, userController, which implements UserController interface.
func NewAuthenticationController() AuthenticationController {
	return authenticationController{
		authenticationService: services.NewAuthenticationService(),
	}
}

// Matches /login of http post action.
func (this authenticationController) Login(ctx *gin.Context) {
	// If the posted data structure is not shared by different controller functions you can define it here.
	var postedData struct {
		Username string `json:"username"`
		Password string `json:"password"`
	}

	// Binds data from posted json.
	ctx.BindJSON(&postedData)

	myUserDetails, errorCode := this.authenticationService.AuthenticateByCredential(postedData.Username, postedData.Password)

	if errorCode == "" {
		// Responses with specified http status code and json format result.
		SendDataResponse(ctx, myUserDetails)
	} else {
		AbortWithStatusData(ctx, http.StatusUnauthorized, map[string]string{
			"error": errorCode,
		})
	}
}

// Matches /refresh-token of http post action.
func (this authenticationController) RefreshToken(ctx *gin.Context) {
	// If the posted data structure is not shared by different controller functions you can define it here.
	var postedData struct {
		RefreshToken string `json:"refreshToken"`
	}

	// Binds data from posted json.
	ctx.BindJSON(&postedData)

	myUserDetails, errorCode := this.authenticationService.RefreshToken(postedData.RefreshToken)

	if errorCode == "" {
		// Responses with specified http status code and json format result.
		SendDataResponse(ctx, myUserDetails)
	} else {
		AbortWithStatusData(ctx, http.StatusUnauthorized, map[string]string{
			"error": errorCode,
		})
	}
}

type authenticationController struct {
	authenticationService services.AuthenticationService
}
